/*
 *  Character.cpp
 *  initiativeTracker
 *
 *  Created by Sam Jaffe on 5/4/12.
 *  Copyright 2012 WPI. All rights reserved.
 *
 */

#include <sstream>
#include "Character.h"

#pragma mark Character class methods
#pragma mark Constructors

Character::Character() : Character(-1) {}

Character::Character(const short idn) :
    delay(false),
    idn(idn) {
}

Character::Character(const Character& that, const short idn) :
Character(idn) {
    hp = that.getHp();
    hp_max = that.getHp_max();
    dis = that.getDis();
    name = that.getName();
    ac = that.getAc();
    fort = that.getFort();
    ref = that.getRef();
    will = that.getWill();
}

Character::~Character(){}

Character& Character::operator<<(const int index) {status[index]=true;}
Character& Character::operator>>(const int index) {status[index]=false;}

#pragma mark XML Serialization methods
const std::string Character::toXML() const {
    std::stringstream xmlStream;
    xmlStream << "character name=\"" << name;
    xmlStream << "\" id'" << idn;
    xmlStream << "' type='" << getType();
    xmlStream << "' health='" << hpCode();
    xmlStream << "' base='" << baseCode();
    xmlStream << "' defense='" << defenseCode();
    xmlStream << "' status='" << statusCode();
    xmlStream << "'/>";
    return xmlStream.str();
}

const int Character::hpCode() const {
    return (hp_max << 16) + hp;
}

const int Character::baseCode() const {
    return (init << 8) + (dis << 24) + dot;
}

const int Character::defenseCode() const {
    return (ac << 24) + (fort << 16) + (ref << 8) + will;
}

const int Character::statusCode() const {
    int i;
    int code;
    for (i = 0; i < CHARACTER_STATUS_SIZE; i++)
        if (status[i]) code ^= (1 << i);
    return code;
}

void Character::decodeStatus(const int stats) {
    int i;
    for (i = 0; i < CHARACTER_STATUS_SIZE; i++)
        status[i] = ((stats & (1 << i)) != 0);
}

//---------------------------------------------------------

#pragma mark NPC class methods
#pragma mark Contructors

NPC::NPC() : NPC(-1, false, 0){}

NPC::NPC(bool isAllied) : NPC(-1, isAllied, 1) {}

NPC::NPC(short idn, bool isAllied) : NPC(idn, isAllied, 1) {
    setFull_name();
}

NPC::NPC(bool isAllied, unsigned short count) : NPC(-1, isAllied, count) {
}

NPC::NPC(short idn, bool isAllied, unsigned short count)
: Character(idn), allied(isAllied), count(count) {
setFull_name();
}

NPC::NPC(const NPC& that, const short idn) : Character((Character) that, idn), allied(that.isAllied()) {}

NPC::~NPC(){}

#pragma mark Getters/Setters

void NPC::setCount(unsigned short count) {
    this->count = count;
    setFull_name();
}

void NPC::setName(const std::string name) {
    Character::setName(name);
    setFull_name();
}

void NPC::setFull_name() {
    std::stringstream ss;
    ss << Character::getName() << "(" << count << ")";
    full_name = ss.str();
}

#pragma mark XML Serialization method

const std::string NPC::baseCode() const {
    return (getInit() << 8) + (count << 16) + (getDis() << 24) + getDot();
}

//---------------------------------------------------------

#pragma mark PC class methods
#pragma mark Constructors

PC::PC() {}

PC::PC(unsigned short idn) : Character(idn) {}

PC::~PC(){}

#pragma mark Getters/Setters

void PC::modHp(const short hp) {
    if (hp > 0)
        modTemp(hp);
    if (temp < 0) {
        Character::modHp(temp);
        nullTemp();
    }
}

void PC::setHp_max(const unsigned short hp_max) {
    Character::setHp_max(hp_max);
    surgeVal = hp_max/4;
}

void PC::setTemp(const short newtemp) {
    temp = newtemp;
    if (temp < 0) {
        Character::modHp(temp);
        nullTemp();
    }
}

#pragma mark Healing methods

void PC::recover(const unsigned short health) {
    short hp = getHp();
    if (hp + health > getHp_max()) {setHp(getHp_max());}
    else {setHp(hp+health);}
}
const unsigned short PC::surge(const unsigned short bonus) {
    surgeLeft--;
    recover(getSurgevalue()+bonus);
    return bonus;
}

#pragma mark XML Serialization methods

const std::string PC::playerData() const {
    std::stringstream ss;
    ss << (surgeLeft + (surgeMax << 8) + (temp << 16));
    return " pname='" + player + "' player='" + ss.str() + "'";
}

const std::string PC::toXML() const {
    std::string xmlString = Character::toXML();
    return xmlString.substr(0, xmlString.size()-3) + playerData() + "/>";
}
